#ifndef H265NALPARSER_HPP
#define H265NalParser.hpp
#include <malloc.h>
#include <stdint.h>

#include <vector>

#include "bs.h"
#include "NalParserCommon.h"

#define MAX_NUM_REF_PICS 16 ///< max. number of pictures used for reference
#define H265_SAR_Extended  255        // Extended_SAR

#define min(a,b)            (((a) < (b)) ? (a) : (b))

using std::vector;

/**
   Network Abstraction Layer (NAL) unit
   @see 7.3.1 NAL unit syntax
*/
typedef struct
{
    int forbidden_zero_bit;
    int nal_unit_type;
    int nuh_layer_id;
    int nuh_temporal_id_plus1;

    void* parsed; // FIXME
    int sizeof_parsed;

    //uint8_t* rbsp_buf;
    //int rbsp_size;
} h265_nal_t;


typedef struct
{
    int payloadType;
    int payloadSize;
    uint8_t* payload;
} h265_sei_t;


/**
   Profile, tier and level
   @see 7.3.3 Profile, tier and level syntax
*/
typedef struct
{
    uint8_t general_profile_space;
    uint8_t general_tier_flag;
    uint8_t general_profile_idc;
    uint8_t general_profile_compatibility_flag[32];
    uint8_t general_progressive_source_flag;
    uint8_t general_interlaced_source_flag;
    uint8_t general_non_packed_constraint_flag;
    uint8_t general_frame_only_constraint_flag;
    uint8_t general_max_12bit_constraint_flag;
    uint8_t general_max_10bit_constraint_flag;
    uint8_t general_max_8bit_constraint_flag;
    uint8_t general_max_422chroma_constraint_flag;
    uint8_t general_max_420chroma_constraint_flag;
    uint8_t general_max_monochrome_constraint_flag;
    uint8_t general_intra_constraint_flag;
    uint8_t general_one_picture_only_constraint_flag;
    uint8_t general_lower_bit_rate_constraint_flag;
    uint64_t general_reserved_zero_34bits; // todo
    uint64_t general_reserved_zero_43bits; // todo
    uint8_t general_inbld_flag;
    uint8_t general_reserved_zero_bit;
    uint8_t general_level_idc;
    vector<uint8_t> sub_layer_profile_present_flag;
    vector<uint8_t> sub_layer_level_present_flag;
    uint8_t reserved_zero_2bits[8];
    vector<uint8_t> sub_layer_profile_space;
    vector<uint8_t> sub_layer_tier_flag;
    vector<uint8_t> sub_layer_profile_idc;
    vector<vector<uint8_t> > sub_layer_profile_compatibility_flag;
    vector<uint8_t> sub_layer_progressive_source_flag;
    vector<uint8_t> sub_layer_interlaced_source_flag;
    vector<uint8_t> sub_layer_non_packed_constraint_flag;
    vector<uint8_t> sub_layer_frame_only_constraint_flag;
    vector<uint8_t> sub_layer_max_12bit_constraint_flag;
    vector<uint8_t> sub_layer_max_10bit_constraint_flag;
    vector<uint8_t> sub_layer_max_8bit_constraint_flag;
    vector<uint8_t> sub_layer_max_422chroma_constraint_flag;
    vector<uint8_t> sub_layer_max_420chroma_constraint_flag;
    vector<uint8_t> sub_layer_max_monochrome_constraint_flag;
    vector<uint8_t> sub_layer_intra_constraint_flag;
    vector<uint8_t> sub_layer_one_picture_only_constraint_flag;
    vector<uint8_t> sub_layer_lower_bit_rate_constraint_flag;
    vector<uint64_t> sub_layer_reserved_zero_34bits;
    vector<uint64_t> sub_layer_reserved_zero_43bits;
    vector<uint8_t> sub_layer_inbld_flag;
    vector<uint8_t> sub_layer_reserved_zero_bit;
    vector<uint8_t> sub_layer_level_idc;

} profile_tier_level_t;

typedef struct
{
    vector<int> bit_rate_value_minus1;
    vector<int> cpb_size_value_minus1;
    vector<int> cpb_size_du_value_minus1;
    vector<int> bit_rate_du_value_minus1;
    vector<uint8_t> cbr_flag;
} sub_layer_hrd_parameters_t;


/**
E.2.2  HRD parameters syntax
*/
typedef struct
{
    uint8_t nal_hrd_parameters_present_flag;
    uint8_t vcl_hrd_parameters_present_flag;
      uint8_t sub_pic_hrd_params_present_flag;
        uint8_t tick_divisor_minus2;
        uint8_t du_cpb_removal_delay_increment_length_minus1;
        uint8_t sub_pic_cpb_params_in_pic_timing_sei_flag;
        uint8_t dpb_output_delay_du_length_minus1;
      uint8_t bit_rate_scale;
      uint8_t cpb_size_scale;
      uint8_t cpb_size_du_scale;
      uint8_t initial_cpb_removal_delay_length_minus1;
      uint8_t au_cpb_removal_delay_length_minus1;
      uint8_t dpb_output_delay_length_minus1;
    vector<uint8_t> fixed_pic_rate_general_flag;
    vector<uint8_t> fixed_pic_rate_within_cvs_flag;
    vector<int> elemental_duration_in_tc_minus1;
    vector<uint8_t> low_delay_hrd_flag;
    vector<int> cpb_cnt_minus1;
    sub_layer_hrd_parameters_t sub_layer_hrd_parameters; // nal
    sub_layer_hrd_parameters_t sub_layer_hrd_parameters_v; // vlc
} hrd_parameters_t;


/**
   Video Parameter Set
   @see 7.3.2.1 Video parameter set RBSP syntax
*/
typedef struct
{
    uint8_t vps_video_parameter_set_id; // u(4)
    uint8_t vps_base_layer_internal_flag; // u(1)
    uint8_t vps_base_layer_available_flag; // u(1)
    uint8_t vps_max_layers_minus1; // u(6)
    uint8_t vps_max_sub_layers_minus1; // u(3)
    uint8_t vps_temporal_id_nesting_flag; // u(1)
    int vps_reserved_0xffff_16bits; // u(16)
    profile_tier_level_t ptl;
    uint8_t vps_sub_layer_ordering_info_present_flag;
    // Sublayers
    int vps_max_dec_pic_buffering_minus1[8]; // max u(3)
    int vps_max_num_reorder_pics[8];
    int vps_max_latency_increase_plus1[8];
    uint8_t vps_max_layer_id;
    int vps_num_layer_sets_minus1;
    vector<vector<uint8_t> > layer_id_included_flag;
    uint8_t vps_timing_info_present_flag;
      int vps_num_units_in_tick;
      int vps_time_scale;
      uint8_t vps_poc_proportional_to_timing_flag;
        int vps_num_ticks_poc_diff_one_minus1;
      int vps_num_hrd_parameters;
      vector<int> hrd_layer_set_idx;
      vector<uint8_t> cprms_present_flag;
      hrd_parameters_t hrd_parameters;
    uint8_t vps_extension_flag;
      uint8_t vps_extension_data_flag;
} h265_vps_t;

/**
7.3.4  Scaling list data syntax
*/
typedef struct
{
    int scaling_list_pred_mode_flag[4][6];
    int scaling_list_pred_matrix_id_delta[4][6];
    int scaling_list_dc_coef_minus8[4][6];
    int ScalingList[4][6][64];
    int coefNum;
} scaling_list_data_t;


typedef struct
{
    int m_numberOfPictures;
    int m_numberOfNegativePictures;
    int m_numberOfPositivePictures;
    int m_numberOfLongtermPictures;
    int m_deltaPOC[MAX_NUM_REF_PICS];
    int m_POC[MAX_NUM_REF_PICS];
    int m_used[MAX_NUM_REF_PICS];
    int m_interRPSPrediction;
    int m_deltaRIdxMinus1;
    int m_deltaRPS;
    int m_numRefIdc;
    int m_refIdc[MAX_NUM_REF_PICS+1];
    int m_bCheckLTMSB[MAX_NUM_REF_PICS];
    int m_pocLSBLT[MAX_NUM_REF_PICS];
    int m_deltaPOCMSBCycleLT[MAX_NUM_REF_PICS];
    int m_deltaPocMSBPresentFlag[MAX_NUM_REF_PICS];
} referencePictureSets_t;


typedef struct
{
    uint8_t inter_ref_pic_set_prediction_flag;
    int delta_idx_minus1;
    uint8_t delta_rps_sign;
    int abs_delta_rps_minus1;
    vector<uint8_t> used_by_curr_pic_flag;
    vector<uint8_t> use_delta_flag;
    int num_negative_pics;
    int num_positive_pics;

#if 1
    vector<int> delta_poc_s0_minus1;
    vector<uint8_t> used_by_curr_pic_s0_flag;
    vector<int> delta_poc_s1_minus1;
    vector<uint8_t> used_by_curr_pic_s1_flag;
#else
    int delta_poc_s0_minus1[16];
    uint8_t used_by_curr_pic_s0_flag[16];
    int delta_poc_s1_minus1[16];
    uint8_t used_by_curr_pic_s1_flag[16];
#endif
} st_ref_pic_set_t;


/**
E.2.1  VUI parameters syntax
*/
typedef struct
{
    uint8_t aspect_ratio_info_present_flag;
      uint8_t aspect_ratio_idc;
      int sar_width;
      int sar_height;
    uint8_t overscan_info_present_flag;
      uint8_t overscan_appropriate_flag;
    uint8_t video_signal_type_present_flag;
      uint8_t video_format;
      uint8_t video_full_range_flag;
      uint8_t colour_description_present_flag;
        uint8_t colour_primaries;
        uint8_t transfer_characteristics;
        uint8_t matrix_coeffs;
    uint8_t chroma_loc_info_present_flag;
      int chroma_sample_loc_type_top_field;
      int chroma_sample_loc_type_bottom_field;
    uint8_t neutral_chroma_indication_flag;
    uint8_t field_seq_flag;
    uint8_t frame_field_info_present_flag;
    uint8_t default_display_window_flag;
      int def_disp_win_left_offset;
      int def_disp_win_right_offset;
      int def_disp_win_top_offset;
      int def_disp_win_bottom_offset;
    uint8_t vui_timing_info_present_flag;
      uint32_t vui_num_units_in_tick;
      uint32_t vui_time_scale;
      uint8_t vui_poc_proportional_to_timing_flag;
        int vui_num_ticks_poc_diff_one_minus1;
      uint8_t vui_hrd_parameters_present_flag;
      hrd_parameters_t hrd_parameters;
    uint8_t bitstream_restriction_flag;
      uint8_t tiles_fixed_structure_flag;
      uint8_t motion_vectors_over_pic_boundaries_flag;
      uint8_t restricted_ref_pic_lists_flag;
      int min_spatial_segmentation_idc;
      int max_bytes_per_pic_denom;
      int max_bits_per_min_cu_denom;
      int log2_max_mv_length_horizontal;
      int log2_max_mv_length_vertical;
} vui_parameters_t;


/**
sps_range_extension
@see 7.3.2.3.1  General picture parameter set RBSP syntax
*/
typedef struct
{
    uint8_t transform_skip_rotation_enabled_flag;
    uint8_t transform_skip_context_enabled_flag;
    uint8_t implicit_rdpcm_enabled_flag;
    uint8_t explicit_rdpcm_enabled_flag;
    uint8_t extended_precision_processing_flag;
    uint8_t intra_smoothing_disabled_flag;
    uint8_t high_precision_offsets_enabled_flag;
    uint8_t persistent_rice_adaptation_enabled_flag;
    uint8_t cabac_bypass_alignment_enabled_flag;
} sps_range_extension_t;

/**
   Sequence Parameter Set
   @see 7.3.2.2 Sequence parameter set RBSP syntax
*/
typedef struct
{
    uint8_t sps_video_parameter_set_id;
    uint8_t sps_max_sub_layers_minus1;
    uint8_t sps_temporal_id_nesting_flag;
    profile_tier_level_t ptl;
    int sps_seq_parameter_set_id;
    int chroma_format_idc;
    uint8_t separate_colour_plane_flag;
    int pic_width_in_luma_samples;
    int pic_height_in_luma_samples;
    int conformance_window_flag;
      int conf_win_left_offset;
      int conf_win_right_offset;
      int conf_win_top_offset;
      int conf_win_bottom_offset;
    int bit_depth_luma_minus8;
    int bit_depth_chroma_minus8;
    int log2_max_pic_order_cnt_lsb_minus4;
    uint8_t sps_sub_layer_ordering_info_present_flag;
    int sps_max_dec_pic_buffering_minus1[8]; // max u(3)
    int sps_max_num_reorder_pics[8];
    int sps_max_latency_increase_plus1[8];
    int log2_min_luma_coding_block_size_minus3;
    int log2_diff_max_min_luma_coding_block_size;
    int log2_min_luma_transform_block_size_minus2;
    int log2_diff_max_min_luma_transform_block_size;
    int max_transform_hierarchy_depth_inter;
    int max_transform_hierarchy_depth_intra;
    uint8_t scaling_list_enabled_flag;
      uint8_t sps_infer_scaling_list_flag;
      int sps_scaling_list_ref_layer_id;
      int sps_scaling_list_data_present_flag;
        scaling_list_data_t scaling_list_data;
    uint8_t amp_enabled_flag;
    uint8_t sample_adaptive_offset_enabled_flag;
    uint8_t pcm_enabled_flag;
      uint8_t pcm_sample_bit_depth_luma_minus1;
      uint8_t pcm_sample_bit_depth_chroma_minus1;
      int log2_min_pcm_luma_coding_block_size_minus3;
      int log2_diff_max_min_pcm_luma_coding_block_size;
      uint8_t pcm_loop_filter_disabled_flag;
    int num_short_term_ref_pic_sets;
    vector<st_ref_pic_set_t> st_ref_pic_set;
    vector<referencePictureSets_t> m_RPSList; // store
    uint8_t long_term_ref_pics_present_flag;
      int num_long_term_ref_pics_sps;
      int lt_ref_pic_poc_lsb_sps_bytes;
      vector<int> lt_ref_pic_poc_lsb_sps;
      vector<uint8_t> used_by_curr_pic_lt_sps_flag;
    uint8_t sps_temporal_mvp_enabled_flag;
    uint8_t strong_intra_smoothing_enabled_flag;
    uint8_t vui_parameters_present_flag;
      vui_parameters_t vui;
    uint8_t sps_extension_present_flag;
      uint8_t sps_range_extension_flag;
      uint8_t sps_multilayer_extension_flag;
      uint8_t sps_3d_extension_flag;
      uint8_t sps_extension_5bits;
    sps_range_extension_t sps_range_extension;
    uint8_t inter_view_mv_vert_constraint_flag ; //sps_multilayer_extension_t sps_multilayer_extension;
    //sps_3d_extension_t sps_3d_extension;
    //int sps_extension_data_flag; // no need
    // rbsp_trailing_bits()...
} h265_sps_t;


/**
 @see 7.3.2.3.2  Picture parameter set range extension syntax
*/
typedef struct
{
    int log2_max_transform_skip_block_size_minus2;
    uint8_t cross_component_prediction_enabled_flag;
    uint8_t chroma_qp_offset_list_enabled_flag;
      int diff_cu_chroma_qp_offset_depth;
      int chroma_qp_offset_list_len_minus1;
      vector<int> cb_qp_offset_list;
      vector<int> cr_qp_offset_list;
    int log2_sao_offset_scale_luma;
    int log2_sao_offset_scale_chroma;
} pps_range_extension_t;


/**
   Picture Parameter Set
   @see 7.3.2.3.1 General picture parameter set RBSP syntax
*/
typedef struct
{
    uint8_t pps_pic_parameter_set_id;
    uint8_t pps_seq_parameter_set_id;
    uint8_t dependent_slice_segments_enabled_flag;
    uint8_t output_flag_present_flag;
    uint8_t num_extra_slice_header_bits;
    uint8_t sign_data_hiding_enabled_flag;
    uint8_t cabac_init_present_flag;
    int num_ref_idx_l0_default_active_minus1;
    int num_ref_idx_l1_default_active_minus1;
    int init_qp_minus26;
    uint8_t constrained_intra_pred_flag;
    uint8_t transform_skip_enabled_flag;
    uint8_t cu_qp_delta_enabled_flag;
    int diff_cu_qp_delta_depth;
    int pps_cb_qp_offset;
    int pps_cr_qp_offset;
    uint8_t pps_slice_chroma_qp_offsets_present_flag;
    uint8_t weighted_pred_flag;
    int weighted_bipred_flag;
    uint8_t transquant_bypass_enabled_flag;
    uint8_t tiles_enabled_flag;
    uint8_t entropy_coding_sync_enabled_flag;
      int num_tile_columns_minus1;
      int num_tile_rows_minus1;
      int uniform_spacing_flag;
        vector<int> column_width_minus1;
        vector<int> row_height_minus1;
      uint8_t loop_filter_across_tiles_enabled_flag;
    uint8_t pps_loop_filter_across_slices_enabled_flag;
    uint8_t deblocking_filter_control_present_flag;
      uint8_t deblocking_filter_override_enabled_flag;
      uint8_t pps_deblocking_filter_disabled_flag;
        int pps_beta_offset_div2;
        int pps_tc_offset_div2;
    uint8_t pps_scaling_list_data_present_flag;
      scaling_list_data_t scaling_list_data;
    uint8_t lists_modification_present_flag;
    int log2_parallel_merge_level_minus2;
    uint8_t slice_segment_header_extension_present_flag;
    uint8_t pps_extension_present_flag;
      uint8_t pps_range_extension_flag;
      uint8_t pps_multilayer_extension_flag;
      uint8_t pps_3d_extension_flag;
      uint8_t pps_extension_5bits;
    pps_range_extension_t pps_range_extension;
    //pps_multilayer_extension_t pps_multilayer_extension;
    //pps_3d_extension_t pps_3d_extension;
    uint8_t pps_extension_data_flag;
    // rbsp_trailing_bits( ) ...
} h265_pps_t;


/**
   Access unit delimiter
   @see 7.3.2.5  Access unit delimiter RBSP syntax
*/
typedef struct
{
    uint8_t pic_type;
} h265_aud_t;


typedef struct
{
    uint8_t ref_pic_list_modification_flag_l0;
    uint32_t list_entry_l0[32]; // according to HM16.6 source code
    uint8_t ref_pic_list_modification_flag_l1;
    uint32_t list_entry_l1[32];
} ref_pic_lists_modification_t;


/**
   Weighted prediction table
   @see 7.3.6.3  Weighted prediction parameters syntax
*/
typedef struct
{
    int luma_log2_weight_denom;
    int delta_chroma_log2_weight_denom;
    vector<uint8_t> luma_weight_l0_flag;
    vector<uint8_t> chroma_weight_l0_flag;
    vector<int> delta_luma_weight_l0;
    vector<int> luma_offset_l0;
    vector<vector <int> > delta_chroma_weight_l0;
    vector<vector <int> > delta_chroma_offset_l0;
    vector<uint8_t> luma_weight_l1_flag;
    vector<uint8_t> chroma_weight_l1_flag;
    vector<int> delta_luma_weight_l1;
    vector<int> luma_offset_l1;
    vector<vector<int> > delta_chroma_weight_l1;
    vector<vector<int> > delta_chroma_offset_l1;
} pred_weight_table_t;



/**
  Slice Header
  @see 7.3.6.1  General slice segment header syntax
*/
typedef struct
{
    int read_slice_type; // see if we only read slice type and return

    int first_slice_segment_in_pic_flag;
    uint8_t no_output_of_prior_pics_flag;
    int slice_pic_parameter_set_id;
      uint8_t dependent_slice_segment_flag;
      int slice_segment_address;
      int slice_segment_address_bytes;
        vector<uint8_t> slice_reserved_flag;
        int slice_type;
        uint8_t pic_output_flag;
        int colour_plane_id;
        int slice_pic_order_cnt_lsb_bytes;
        int slice_pic_order_cnt_lsb;
        uint8_t short_term_ref_pic_set_sps_flag;
        st_ref_pic_set_t st_ref_pic_set;
        referencePictureSets_t* m_pRPS;
        referencePictureSets_t m_localRPS;
        int short_term_ref_pic_set_idx;
        int short_term_ref_pic_set_idx_bytes;
        int num_long_term_sps;
        int num_long_term_pics;
        vector<int> lt_idx_sps;
        vector<int> poc_lsb_lt;
        vector<uint8_t> used_by_curr_pic_lt_flag;
        vector<uint8_t> delta_poc_msb_present_flag;
        vector<int> delta_poc_msb_cycle_lt;
    uint8_t slice_temporal_mvp_enabled_flag;
    uint8_t slice_sao_luma_flag;
    uint8_t slice_sao_chroma_flag;
    uint8_t num_ref_idx_active_override_flag;
    int num_ref_idx_l0_active_minus1;
    int num_ref_idx_l1_active_minus1;
    ref_pic_lists_modification_t ref_pic_lists_modification;
    uint8_t mvd_l1_zero_flag;
    uint8_t cabac_init_flag;
    uint8_t collocated_from_l0_flag;
    int collocated_ref_idx;
    pred_weight_table_t pred_weight_table;
    int five_minus_max_num_merge_cand;
    int slice_qp_delta;
    int slice_cb_qp_offset;
    int slice_cr_qp_offset;
    uint8_t cu_chroma_qp_offset_enabled_flag;
    uint8_t deblocking_filter_override_flag;
    uint8_t slice_deblocking_filter_disabled_flag;
    int slice_beta_offset_div2;
    int slice_tc_offset_div2;
    uint8_t slice_loop_filter_across_slices_enabled_flag;
    int num_entry_point_offsets;
    int offset_len_minus1;
    int entry_point_offset_minus1_bytes;
    vector<int> entry_point_offset_minus1;
    int slice_segment_header_extension_length;
    vector<int> slice_segment_header_extension_data_byte;
    // byte_alignment( )...
} h265_slice_header_t;


typedef struct
{
  int rbsp_size;
  uint8_t* rbsp_buf;
} h265_slice_data_rbsp_t;


typedef struct
{
    h265_nal_t* nal;
    h265_vps_t* vps;
    h265_sps_t* sps;
    h265_pps_t* pps;
    h265_aud_t* aud;
    h265_sei_t* sei; //This is a TEMP pointer at whats in h->seis...
    int num_seis;
    h265_slice_header_t* sh;
    h265_slice_data_rbsp_t* slice_data;

    h265_vps_t* vps_table[16];   // --checked
    h265_sps_t* sps_table[32];
    h265_pps_t* pps_table[256];
    h265_sei_t** seis;
    videoinfo_t* info;
} h265_stream_t;


//Table 7-1 NAL unit type codes and NAL unit type classes
enum NalUnitType
{
    NAL_UNIT_CODED_SLICE_TRAIL_N = 0, // 0
    NAL_UNIT_CODED_SLICE_TRAIL_R,     // 1

    NAL_UNIT_CODED_SLICE_TSA_N,       // 2
    NAL_UNIT_CODED_SLICE_TSA_R,       // 3

    NAL_UNIT_CODED_SLICE_STSA_N,      // 4
    NAL_UNIT_CODED_SLICE_STSA_R,      // 5

    NAL_UNIT_CODED_SLICE_RADL_N,      // 6
    NAL_UNIT_CODED_SLICE_RADL_R,      // 7

    NAL_UNIT_CODED_SLICE_RASL_N,      // 8
    NAL_UNIT_CODED_SLICE_RASL_R,      // 9

    NAL_UNIT_RESERVED_VCL_N10,
    NAL_UNIT_RESERVED_VCL_R11,
    NAL_UNIT_RESERVED_VCL_N12,
    NAL_UNIT_RESERVED_VCL_R13,
    NAL_UNIT_RESERVED_VCL_N14,
    NAL_UNIT_RESERVED_VCL_R15,

    NAL_UNIT_CODED_SLICE_BLA_W_LP,    // 16
    NAL_UNIT_CODED_SLICE_BLA_W_RADL,  // 17
    NAL_UNIT_CODED_SLICE_BLA_N_LP,    // 18
    NAL_UNIT_CODED_SLICE_IDR_W_RADL,  // 19
    NAL_UNIT_CODED_SLICE_IDR_N_LP,    // 20
    NAL_UNIT_CODED_SLICE_CRA,         // 21
    NAL_UNIT_RESERVED_IRAP_VCL22,
    NAL_UNIT_RESERVED_IRAP_VCL23,

    NAL_UNIT_RESERVED_VCL24,
    NAL_UNIT_RESERVED_VCL25,
    NAL_UNIT_RESERVED_VCL26,
    NAL_UNIT_RESERVED_VCL27,
    NAL_UNIT_RESERVED_VCL28,
    NAL_UNIT_RESERVED_VCL29,
    NAL_UNIT_RESERVED_VCL30,
    NAL_UNIT_RESERVED_VCL31,

    // non-VCL
    NAL_UNIT_VPS,                     // 32
    NAL_UNIT_SPS,                     // 33
    NAL_UNIT_PPS,                     // 34
    NAL_UNIT_AUD,                     // 35
    NAL_UNIT_EOS,                     // 36
    NAL_UNIT_EOB,                     // 37
    NAL_UNIT_FILLER_DATA,             // 38
    NAL_UNIT_PREFIX_SEI,              // 39
    NAL_UNIT_SUFFIX_SEI,              // 40

    NAL_UNIT_RESERVED_NVCL41,
    NAL_UNIT_RESERVED_NVCL42,
    NAL_UNIT_RESERVED_NVCL43,
    NAL_UNIT_RESERVED_NVCL44,
    NAL_UNIT_RESERVED_NVCL45,
    NAL_UNIT_RESERVED_NVCL46,
    NAL_UNIT_RESERVED_NVCL47,
    NAL_UNIT_UNSPECIFIED_48,
    NAL_UNIT_UNSPECIFIED_49,
    NAL_UNIT_UNSPECIFIED_50,
    NAL_UNIT_UNSPECIFIED_51,
    NAL_UNIT_UNSPECIFIED_52,
    NAL_UNIT_UNSPECIFIED_53,
    NAL_UNIT_UNSPECIFIED_54,
    NAL_UNIT_UNSPECIFIED_55,
    NAL_UNIT_UNSPECIFIED_56,
    NAL_UNIT_UNSPECIFIED_57,
    NAL_UNIT_UNSPECIFIED_58,
    NAL_UNIT_UNSPECIFIED_59,
    NAL_UNIT_UNSPECIFIED_60,
    NAL_UNIT_UNSPECIFIED_61,
    NAL_UNIT_UNSPECIFIED_62,
    NAL_UNIT_UNSPECIFIED_63,
    NAL_UNIT_INVALID,
};


void h265_read_ptl(profile_tier_level_t* ptl, bs_t* b, int profilePresentFlag, int max_sub_layers_minus1)
{
    int i = 0;
    if (profilePresentFlag)
    {
        ptl->general_profile_space = bs_read_u(b, 2);
        ptl->general_tier_flag     =  bs_read_u1(b);
        ptl->general_profile_idc   = bs_read_u(b, 5);
        for (i = 0; i < 32; i++)
        {
            ptl->general_profile_compatibility_flag[i] = bs_read_u1(b);
        }
        ptl->general_progressive_source_flag    = bs_read_u1(b);
        ptl->general_interlaced_source_flag     = bs_read_u1(b);
        ptl->general_non_packed_constraint_flag = bs_read_u1(b);
        ptl->general_frame_only_constraint_flag = bs_read_u1(b);
        if (ptl->general_profile_idc==4 || ptl->general_profile_compatibility_flag[4] ||
            ptl->general_profile_idc==5 || ptl->general_profile_compatibility_flag[5] ||
            ptl->general_profile_idc==6 || ptl->general_profile_compatibility_flag[6] ||
            ptl->general_profile_idc==7 || ptl->general_profile_compatibility_flag[7])
        {
            ptl->general_max_12bit_constraint_flag      = bs_read_u1(b);
            ptl->general_max_10bit_constraint_flag      = bs_read_u1(b);
            ptl->general_max_8bit_constraint_flag       = bs_read_u1(b);
            ptl->general_max_422chroma_constraint_flag  = bs_read_u1(b);
            ptl->general_max_420chroma_constraint_flag  = bs_read_u1(b);
            ptl->general_max_monochrome_constraint_flag = bs_read_u1(b);
            ptl->general_intra_constraint_flag          = bs_read_u1(b);
            ptl->general_one_picture_only_constraint_flag = bs_read_u1(b);
            ptl->general_lower_bit_rate_constraint_flag = bs_read_u1(b);
            uint64_t tmp1 = bs_read_u(b, 32);
            uint64_t tmp2 = bs_read_u(b, 2);
            ptl->general_reserved_zero_34bits = tmp1+tmp2;
        }
        else
        {
            uint64_t tmp1 = bs_read_u(b, 32);
            uint64_t tmp2 = bs_read_u(b, 11);
            ptl->general_reserved_zero_43bits = tmp1+tmp2;
        }
        if ((ptl->general_profile_idc>=1 && ptl->general_profile_idc<=5) ||
            ptl->general_profile_compatibility_flag[1] || ptl->general_profile_compatibility_flag[2] ||
            ptl->general_profile_compatibility_flag[3] || ptl->general_profile_compatibility_flag[4] ||
            ptl->general_profile_compatibility_flag[5])
        {
            ptl->general_inbld_flag = bs_read_u1(b);
        }
        else
        {
            ptl->general_reserved_zero_bit = bs_read_u1(b);
        }
    }
    ptl->general_level_idc = bs_read_u8(b);
    ptl->sub_layer_profile_present_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_level_present_flag.resize(max_sub_layers_minus1);
    for (i = 0; i < max_sub_layers_minus1; i++)
    {
        ptl->sub_layer_profile_present_flag[i] = bs_read_u1(b);
        ptl->sub_layer_level_present_flag[i]   = bs_read_u1(b);
    }
    if (max_sub_layers_minus1 > 0)
    {
        for (i = max_sub_layers_minus1; i < 8; i++)
        {
            ptl->reserved_zero_2bits[i] = bs_read_u(b, 2);
        }
    }
    ptl->sub_layer_profile_space.resize(max_sub_layers_minus1);
    ptl->sub_layer_tier_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_profile_idc.resize(max_sub_layers_minus1);
    ptl->sub_layer_profile_compatibility_flag.resize(max_sub_layers_minus1);
    for (int j = 0; j < max_sub_layers_minus1; j++)
    {
        ptl->sub_layer_profile_compatibility_flag[j].resize(32);
    }
    ptl->sub_layer_progressive_source_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_interlaced_source_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_non_packed_constraint_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_frame_only_constraint_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_max_12bit_constraint_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_max_10bit_constraint_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_max_8bit_constraint_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_max_422chroma_constraint_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_max_420chroma_constraint_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_max_monochrome_constraint_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_intra_constraint_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_one_picture_only_constraint_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_lower_bit_rate_constraint_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_reserved_zero_34bits.resize(max_sub_layers_minus1);
    ptl->sub_layer_reserved_zero_43bits.resize(max_sub_layers_minus1);
    ptl->sub_layer_inbld_flag.resize(max_sub_layers_minus1);
    ptl->sub_layer_reserved_zero_bit.resize(max_sub_layers_minus1);
    ptl->sub_layer_level_idc.resize(max_sub_layers_minus1);
    for (i = 0; i < max_sub_layers_minus1; i++)
    {
        if (ptl->sub_layer_profile_present_flag[i])
        {
            ptl->sub_layer_profile_space[i] = bs_read_u(b, 2);
            ptl->sub_layer_tier_flag[i]     = bs_read_u1(b);
            ptl->sub_layer_profile_idc[i]   = bs_read_u(b, 5);
            for (int j = 0; j < 32; j++)
            {
                ptl->sub_layer_profile_compatibility_flag[i][j] = bs_read_u1(b);
            }
            ptl->sub_layer_progressive_source_flag[i]    = bs_read_u1(b);
            ptl->sub_layer_interlaced_source_flag[i]     = bs_read_u1(b);
            ptl->sub_layer_non_packed_constraint_flag[i] = bs_read_u1(b);
            ptl->sub_layer_frame_only_constraint_flag[i] = bs_read_u1(b);
            if (ptl->sub_layer_profile_idc[i]==4 || ptl->sub_layer_profile_compatibility_flag[i][4] ||
                ptl->sub_layer_profile_idc[i]==5 || ptl->sub_layer_profile_compatibility_flag[i][5] ||
                ptl->sub_layer_profile_idc[i]==6 || ptl->sub_layer_profile_compatibility_flag[i][6] ||
                ptl->sub_layer_profile_idc[i]==7 || ptl->sub_layer_profile_compatibility_flag[i][7])
            {
                ptl->sub_layer_max_12bit_constraint_flag[i]        = bs_read_u1(b);
                ptl->sub_layer_max_10bit_constraint_flag[i]        = bs_read_u1(b);
                ptl->sub_layer_max_8bit_constraint_flag[i]         = bs_read_u1(b);
                ptl->sub_layer_max_422chroma_constraint_flag[i]    = bs_read_u1(b);
                ptl->sub_layer_max_420chroma_constraint_flag[i]    = bs_read_u1(b);
                ptl->sub_layer_max_monochrome_constraint_flag[i]   = bs_read_u1(b);
                ptl->sub_layer_intra_constraint_flag[i] = bs_read_u1(b);
                ptl->sub_layer_one_picture_only_constraint_flag[i] = bs_read_u1(b);
                ptl->sub_layer_lower_bit_rate_constraint_flag[i]   = bs_read_u1(b);
                uint64_t tmp1 = bs_read_u(b, 32);
                uint64_t tmp2 = bs_read_u(b, 2);
                ptl->sub_layer_reserved_zero_34bits[i] = tmp1+tmp2;
            }
            else
            {
                uint64_t tmp1 = bs_read_u(b, 32);
                uint64_t tmp2 = bs_read_u(b, 12);
                ptl->sub_layer_reserved_zero_43bits[i] = tmp1+tmp2;
            }
            // to check
            if ((ptl->sub_layer_profile_idc[i]>=1 && ptl->sub_layer_profile_idc[i]<=5) ||
                ptl->sub_layer_profile_compatibility_flag[i][1] ||
                ptl->sub_layer_profile_compatibility_flag[i][2] ||
                ptl->sub_layer_profile_compatibility_flag[i][3] ||
                ptl->sub_layer_profile_compatibility_flag[i][4] ||
                ptl->sub_layer_profile_compatibility_flag[i][5])
            {
                ptl->sub_layer_inbld_flag[i] = bs_read_u1(b);
            }
            else
            {
                ptl->sub_layer_reserved_zero_bit[i] = bs_read_u1(b);
            }
        }
        if (ptl->sub_layer_level_present_flag[i])
        {
            ptl->sub_layer_level_idc[i] = bs_read_u8(b);
        }
    }
}


// 7.3.4  Scaling list data syntax
void h265_read_scaling_list(scaling_list_data_t* sld, bs_t* b)
{
    for(int sizeId = 0; sizeId < 4; sizeId++)
    {
        for(int matrixId = 0; matrixId < 6; matrixId += ( sizeId == 3 ) ? 3 : 1)
        {
            sld->scaling_list_pred_mode_flag[sizeId][matrixId] = bs_read_u1(b);
            if (!sld->scaling_list_pred_mode_flag[sizeId][matrixId])
            {
                sld->scaling_list_pred_matrix_id_delta[sizeId][matrixId] = bs_read_ue(b);
            }
            else
            {
                int nextCoef = 8;
                int coefNum = min(64, (1 << (4 + (sizeId << 1))));
                sld->coefNum = coefNum; // tmp store
                if (sizeId > 1)
                {
                    sld->scaling_list_dc_coef_minus8[sizeId - 2][matrixId] = bs_read_se(b);
                    nextCoef = sld->scaling_list_dc_coef_minus8[sizeId - 2][matrixId] + 8;
                }
                for (int i = 0; i < sld->coefNum; i++)
                {
                    int scaling_list_delta_coef = bs_read_se(b);
                    nextCoef = (nextCoef + scaling_list_delta_coef + 256) % 256;
                    sld->ScalingList[sizeId][matrixId][i] = nextCoef;
                }
            }
        }
    }
}


// st_ref_pic_set
// 7.3.7  Short-term reference picture set syntax
void h265_read_short_term_ref_pic_set(bs_t* b, h265_sps_t* sps, st_ref_pic_set_t*st, referencePictureSets_t* rps, int stRpsIdx)
{
    st->inter_ref_pic_set_prediction_flag = 0;
    if (stRpsIdx != 0)
    {
        st->inter_ref_pic_set_prediction_flag = bs_read_u1(b);
    }
    if (st->inter_ref_pic_set_prediction_flag)
    {
        st->delta_idx_minus1 = 0;
        if (stRpsIdx == sps->m_RPSList.size())
        {
            st->delta_idx_minus1 = bs_read_ue(b);
        }
        int rIdx = stRpsIdx - 1 - st->delta_idx_minus1;
        referencePictureSets_t* rpsRef = &sps->m_RPSList[rIdx];

        st->delta_rps_sign       = bs_read_u1(b);
        st->abs_delta_rps_minus1 = bs_read_ue(b);
        int deltaRPS = (1 - 2 * st->delta_rps_sign) * (st->abs_delta_rps_minus1 + 1); // delta_RPS
        st->used_by_curr_pic_flag.resize(rpsRef->m_numberOfPictures+1);
        st->use_delta_flag.resize(rpsRef->m_numberOfPictures+1);
        for (int j = 0; j <= rpsRef->m_numberOfPictures; j++)
        {
            st->used_by_curr_pic_flag[j] = bs_read_u1(b);
            int refIdc = st->used_by_curr_pic_flag[j];
            if (!st->used_by_curr_pic_flag[j])
            {
                st->use_delta_flag[j] = bs_read_u1(b);
                refIdc = st->use_delta_flag[j] << 1; //second bit is "1" if refIdc is 2, "0" if refIdc = 0.
            }
            // todo furture
            if (refIdc == 1 || refIdc == 2)
            {

            }
        }
    }
    else
    {
        st->num_negative_pics = bs_read_ue(b);
        st->num_positive_pics = bs_read_ue(b);

        rps->m_numberOfNegativePictures = st->num_negative_pics;
        rps->m_numberOfPositivePictures = st->num_positive_pics;

        // to check...
        st->delta_poc_s0_minus1.resize(st->num_negative_pics);
        st->used_by_curr_pic_s0_flag.resize(st->num_negative_pics);
        for (int i = 0; i < st->num_negative_pics; i++)
        {
            st->delta_poc_s0_minus1[i] = bs_read_ue(b);
            st->used_by_curr_pic_s0_flag[i] = bs_read_u1(b);
            rps->m_used[i] = st->used_by_curr_pic_s0_flag[i];
        }
        st->delta_poc_s1_minus1.resize(st->num_positive_pics);
        st->used_by_curr_pic_s1_flag.resize(st->num_positive_pics);
        for (int i = 0; i < st->num_positive_pics; i++)
        {
            st->delta_poc_s1_minus1[i] = bs_read_ue(b);
            st->used_by_curr_pic_s1_flag[i] = bs_read_u1(b);
            rps->m_used[i + st->num_negative_pics] = st->used_by_curr_pic_s1_flag[i];
        }
        rps->m_numberOfPictures = rps->m_numberOfNegativePictures + rps->m_numberOfPositivePictures;
    }
}


// E.2.3  Sub-layer HRD parameters syntax
// E.3.3  The variable CpbCnt is set equal to cpb_cnt_minus1[ subLayerId ].
void h265_read_sub_layer_hrd_parameters(sub_layer_hrd_parameters_t* subhrd, bs_t* b, int sub_pic_hrd_params_present_flag, int CpbCnt)
{
    subhrd->bit_rate_value_minus1.resize(CpbCnt+1);
    subhrd->cpb_size_value_minus1.resize(CpbCnt+1);
    subhrd->cpb_size_du_value_minus1.resize(CpbCnt+1);
    subhrd->bit_rate_du_value_minus1.resize(CpbCnt+1);
    subhrd->cbr_flag.resize(CpbCnt+1);
    for (int i = 0; i <= CpbCnt; i++)
    {
        subhrd->bit_rate_value_minus1[i] = bs_read_ue(b);
        subhrd->cpb_size_value_minus1[i] = bs_read_ue(b);
        if (sub_pic_hrd_params_present_flag)
        {
            subhrd->cpb_size_du_value_minus1[i] = bs_read_ue(b);
            subhrd->bit_rate_du_value_minus1[i] = bs_read_ue(b);
        }
        subhrd->cbr_flag[i] = bs_read_u1(b);
    }
}


// E.2.2  HRD parameters syntax
void h265_read_hrd_parameters(hrd_parameters_t* hrd, bs_t* b, int commonInfPresentFlag, int maxNumSubLayersMinus1)
{
    if(commonInfPresentFlag)
    {
         hrd->nal_hrd_parameters_present_flag = bs_read_u1(b);
         hrd->vcl_hrd_parameters_present_flag = bs_read_u1(b);
         if (hrd->nal_hrd_parameters_present_flag ||
             hrd->vcl_hrd_parameters_present_flag)
         {
            hrd->sub_pic_hrd_params_present_flag = bs_read_u1(b);
            if (hrd->sub_pic_hrd_params_present_flag)
            {
                hrd->tick_divisor_minus2 = bs_read_u8(b);
                hrd->du_cpb_removal_delay_increment_length_minus1 = bs_read_u(b, 5);
                hrd->sub_pic_cpb_params_in_pic_timing_sei_flag    = bs_read_u1(b);
                hrd->dpb_output_delay_du_length_minus1            = bs_read_u(b, 5);
            }
            hrd->bit_rate_scale  = bs_read_u(b, 4);
            hrd->cpb_size_scale  = bs_read_u(b, 4);
            if (hrd->sub_pic_hrd_params_present_flag)
            {
                hrd->cpb_size_du_scale = bs_read_u(b, 4);
            }
            hrd->initial_cpb_removal_delay_length_minus1 = bs_read_u(b, 5);
            hrd->au_cpb_removal_delay_length_minus1      = bs_read_u(b, 5);
            hrd->dpb_output_delay_length_minus1          = bs_read_u(b, 5);
         }
    }
    hrd->fixed_pic_rate_general_flag.resize(maxNumSubLayersMinus1+1);
    hrd->fixed_pic_rate_within_cvs_flag.resize(maxNumSubLayersMinus1+1);
    hrd->elemental_duration_in_tc_minus1.resize(maxNumSubLayersMinus1+1);
    hrd->low_delay_hrd_flag.resize(maxNumSubLayersMinus1+1);
    hrd->cpb_cnt_minus1.resize(maxNumSubLayersMinus1+1);
    for (int i = 0; i <= maxNumSubLayersMinus1; i++)
    {
        hrd->fixed_pic_rate_general_flag[i] = bs_read_u1(b);
        if (!hrd->fixed_pic_rate_general_flag[i])
        {
            hrd->fixed_pic_rate_within_cvs_flag[i] = bs_read_u1(b);
        }
        if (hrd->fixed_pic_rate_within_cvs_flag[i])
        {
            hrd->elemental_duration_in_tc_minus1[i] = bs_read_ue(b);
        }
        else
        {
            hrd->low_delay_hrd_flag[i] = bs_read_u1(b);
        }
        if (!hrd->low_delay_hrd_flag[i])
        {
            hrd->cpb_cnt_minus1[i] = bs_read_u1(b);
        }
        if(hrd->nal_hrd_parameters_present_flag)
        {
            h265_read_sub_layer_hrd_parameters(&(hrd->sub_layer_hrd_parameters), b, hrd->sub_pic_hrd_params_present_flag, hrd->cpb_cnt_minus1[i]);
        }
        if(hrd->vcl_hrd_parameters_present_flag)
        {
            h265_read_sub_layer_hrd_parameters(&(hrd->sub_layer_hrd_parameters_v), b, hrd->sub_pic_hrd_params_present_flag, hrd->cpb_cnt_minus1[i]);
        }
    }
}


// E.2.1  VUI parameters syntax
void h265_read_vui_parameters(vui_parameters_t* vui, bs_t* b, int maxNumSubLayersMinus1)
{
    vui->aspect_ratio_info_present_flag = bs_read_u1(b);
    if (vui->aspect_ratio_info_present_flag)
    {
        vui->aspect_ratio_idc  = bs_read_u8(b);
        if (vui->aspect_ratio_idc == H265_SAR_Extended)
        {
            vui->sar_width  = bs_read_u(b, 16);
            vui->sar_height = bs_read_u(b, 16);
        }
    }
    vui->overscan_info_present_flag = bs_read_u1(b);
    if (vui->overscan_info_present_flag)
    {
        vui->overscan_appropriate_flag  = bs_read_u1(b);
    }
    vui->video_signal_type_present_flag = bs_read_u1(b);
    if (vui->video_signal_type_present_flag)
    {
        vui->video_format          = bs_read_u(b, 3);
        vui->video_full_range_flag = bs_read_u1(b);
        vui->colour_description_present_flag = bs_read_u1(b);
        if (vui->colour_description_present_flag)
        {
            vui->colour_primaries  = bs_read_u8(b);
            vui->transfer_characteristics = bs_read_u8(b);
            vui->matrix_coeffs     = bs_read_u8(b);
        }
    }
    vui->chroma_loc_info_present_flag = bs_read_u1(b);
    if (vui->chroma_loc_info_present_flag)
    {
        vui->chroma_sample_loc_type_top_field    = bs_read_ue(b);
        vui->chroma_sample_loc_type_bottom_field = bs_read_ue(b);
    }
    vui->neutral_chroma_indication_flag = bs_read_u1(b);
    vui->field_seq_flag                 = bs_read_u1(b);
    vui->frame_field_info_present_flag  = bs_read_u1(b);
    vui->default_display_window_flag    = bs_read_u1(b);
    if (vui->default_display_window_flag)
    {
        vui->def_disp_win_left_offset   = bs_read_ue(b);
        vui->def_disp_win_right_offset  = bs_read_ue(b);
        vui->def_disp_win_top_offset    = bs_read_ue(b);
        vui->def_disp_win_bottom_offset = bs_read_ue(b);
    }
    vui->vui_timing_info_present_flag   = bs_read_u1(b);
    if (vui->vui_timing_info_present_flag)
    {
        vui->vui_num_units_in_tick     = bs_read_u(b, 32);
        vui->vui_time_scale            = bs_read_u(b, 32);
        vui->vui_poc_proportional_to_timing_flag = bs_read_u1(b);
        if (vui->vui_poc_proportional_to_timing_flag)
        {
            vui->vui_num_ticks_poc_diff_one_minus1 = bs_read_ue(b);
        }
        vui->vui_hrd_parameters_present_flag = bs_read_u1(b);
        if (vui->vui_hrd_parameters_present_flag)
        {
            h265_read_hrd_parameters(&vui->hrd_parameters, b, 1, maxNumSubLayersMinus1);
        }
    }
    vui->bitstream_restriction_flag = bs_read_u1(b);
    if (vui->bitstream_restriction_flag)
    {
        vui->tiles_fixed_structure_flag     = bs_read_u1(b);
        vui->motion_vectors_over_pic_boundaries_flag = bs_read_u1(b);
        vui->restricted_ref_pic_lists_flag  = bs_read_u1(b);
        vui->min_spatial_segmentation_idc   = bs_read_ue(b);
        vui->max_bytes_per_pic_denom        = bs_read_ue(b);
        vui->max_bits_per_min_cu_denom      = bs_read_ue(b);
        vui->log2_max_mv_length_horizontal  = bs_read_ue(b);
        vui->log2_max_mv_length_vertical    = bs_read_ue(b);
    }
}


int h265_more_rbsp_trailing_data(bs_t* b) { return !bs_eof(b); }


//7.3.2.11 RBSP trailing bits syntax
void h265_read_rbsp_trailing_bits(bs_t* b)
{
    int rbsp_stop_one_bit = bs_read_u1( b ); // equal to 1

    while( !bs_byte_aligned(b) )
    {
        int rbsp_alignment_zero_bit = bs_read_u1( b ); // equal to 0 7 bits
    }
}


//7.3.2.1 Sequence parameter set RBSP syntax
void  h265_read_sps_rbsp(h265_stream_t* h, bs_t* b)
{
    // NOTE 不能直接赋值给sps，因为还未知是哪一个sps。

    int sps_video_parameter_set_id = 0;
    int sps_max_sub_layers_minus1 = 0;
    int sps_temporal_id_nesting_flag = 0;
    int sps_seq_parameter_set_id = 0;
    profile_tier_level_t profile_tier_level;

    sps_video_parameter_set_id = bs_read_u(b, 4);
    sps_max_sub_layers_minus1 = bs_read_u(b, 3);
    sps_temporal_id_nesting_flag = bs_read_u1(b);

    // profile tier level...
    memset(&profile_tier_level, '\0', sizeof(profile_tier_level_t));

    h265_read_ptl(&profile_tier_level, b, 1, sps_max_sub_layers_minus1);

    sps_seq_parameter_set_id = bs_read_ue(b);
    // 选择正确的sps表
    h->sps = h->sps_table[sps_seq_parameter_set_id];
    h265_sps_t* sps = h->sps;
    memset(sps, 0, sizeof(h265_sps_t));

    sps->sps_video_parameter_set_id   = sps_video_parameter_set_id;
    sps->sps_max_sub_layers_minus1    = sps_max_sub_layers_minus1;
    sps->sps_temporal_id_nesting_flag = sps_temporal_id_nesting_flag;
    
    memcpy(&(sps->ptl), &profile_tier_level, sizeof(profile_tier_level_t)); // ptl

    sps->sps_seq_parameter_set_id     = sps_seq_parameter_set_id;
    sps->chroma_format_idc     = bs_read_ue(b);
    h->info->chroma_format_idc = sps->chroma_format_idc;
    if (sps->chroma_format_idc == 3)
    {
        sps->separate_colour_plane_flag = bs_read_u1(b);
    }
    sps->pic_width_in_luma_samples  = bs_read_ue(b);
    sps->pic_height_in_luma_samples = bs_read_ue(b);

    h->info->width  = sps->pic_width_in_luma_samples;
    h->info->height = sps->pic_height_in_luma_samples;

    sps->conformance_window_flag    = bs_read_u1(b);
    if (sps->conformance_window_flag)
    {
        sps->conf_win_left_offset   = bs_read_ue(b);
        sps->conf_win_right_offset  = bs_read_ue(b);
        sps->conf_win_top_offset    = bs_read_ue(b);
        sps->conf_win_bottom_offset = bs_read_ue(b);

        // calc width & height again...
        h->info->crop_left = sps->conf_win_left_offset;
        h->info->crop_right = sps->conf_win_right_offset;
        h->info->crop_top = sps->conf_win_top_offset;
        h->info->crop_bottom = sps->conf_win_bottom_offset;

        // 根据Table6-1及7.4.3.2.1重新计算宽、高
        // 注意：手册里加1，实际上不用
        // 参考：https://github.com/mbunkus/mkvtoolnix/issues/1152
        int sub_width_c  = ((1 == sps->chroma_format_idc) || (2 == sps->chroma_format_idc)) && (0 == sps->separate_colour_plane_flag) ? 2 : 1;
        int sub_height_c =  (1 == sps->chroma_format_idc)                                   && (0 == sps->separate_colour_plane_flag) ? 2 : 1;
        h->info->width  -= (sub_width_c*sps->conf_win_right_offset + sub_width_c*sps->conf_win_left_offset);
        h->info->height -= (sub_height_c*sps->conf_win_bottom_offset + sub_height_c*sps->conf_win_top_offset);
    }

    sps->bit_depth_luma_minus8   = bs_read_ue(b);
    sps->bit_depth_chroma_minus8 = bs_read_ue(b);

    // bit depth
    h->info->bit_depth_luma = sps->bit_depth_luma_minus8 + 8;
    h->info->bit_depth_chroma = sps->bit_depth_chroma_minus8 + 8;

    sps->log2_max_pic_order_cnt_lsb_minus4 = bs_read_ue(b);

    sps->sps_sub_layer_ordering_info_present_flag = bs_read_u1(b);
    for (int i = (sps->sps_sub_layer_ordering_info_present_flag ? 0 : sps->sps_max_sub_layers_minus1);
        i <= sps->sps_max_sub_layers_minus1; i++ )
    {
        sps->sps_max_dec_pic_buffering_minus1[i] = bs_read_ue(b);
        sps->sps_max_num_reorder_pics[i]         = bs_read_ue(b);
        sps->sps_max_latency_increase_plus1[i]   = bs_read_ue(b);
    }

    sps->log2_min_luma_coding_block_size_minus3      = bs_read_ue(b);
    sps->log2_diff_max_min_luma_coding_block_size    = bs_read_ue(b);
    sps->log2_min_luma_transform_block_size_minus2   = bs_read_ue(b);
    sps->log2_diff_max_min_luma_transform_block_size = bs_read_ue(b);
    sps->max_transform_hierarchy_depth_inter         = bs_read_ue(b);
    sps->max_transform_hierarchy_depth_intra         = bs_read_ue(b);

    sps->scaling_list_enabled_flag = bs_read_u1(b);
    if (sps->scaling_list_enabled_flag)
    {
        sps->sps_scaling_list_data_present_flag = bs_read_u1(b);
        if (sps->sps_scaling_list_data_present_flag)
        {
            // scaling_list_data()
            h265_read_scaling_list(&(sps->scaling_list_data), b);
        }
    }

    sps->amp_enabled_flag = bs_read_u1(b);
    sps->sample_adaptive_offset_enabled_flag = bs_read_u1(b);
    sps->pcm_enabled_flag = bs_read_u1(b);
    if (sps->pcm_enabled_flag)
    {
        sps->pcm_sample_bit_depth_luma_minus1   = bs_read_u(b, 4);
        sps->pcm_sample_bit_depth_chroma_minus1 = bs_read_u(b, 4);
        sps->log2_min_pcm_luma_coding_block_size_minus3   = bs_read_ue(b);
        sps->log2_diff_max_min_pcm_luma_coding_block_size = bs_read_ue(b);
        sps->pcm_loop_filter_disabled_flag      = bs_read_u1(b);
    }

    sps->num_short_term_ref_pic_sets = bs_read_ue(b);
    // 根据num_short_term_ref_pic_sets创建数组
    sps->st_ref_pic_set.resize(sps->num_short_term_ref_pic_sets);
    sps->m_RPSList.resize(sps->num_short_term_ref_pic_sets); // 确定一共有多少个RPS列表
    referencePictureSets_t* rps = NULL;
    st_ref_pic_set_t* st = NULL;
    for (int i = 0; i < sps->num_short_term_ref_pic_sets; i++)
    {
        st = &sps->st_ref_pic_set[i];
        rps = &sps->m_RPSList[i];
        h265_read_short_term_ref_pic_set(b, sps, st, rps, i);
    }

    sps->long_term_ref_pics_present_flag = bs_read_u1(b);
    if (sps->long_term_ref_pics_present_flag)
    {
        sps->num_long_term_ref_pics_sps = bs_read_ue(b);
        sps->lt_ref_pic_poc_lsb_sps.resize(sps->num_long_term_ref_pics_sps);
        sps->used_by_curr_pic_lt_sps_flag.resize(sps->num_long_term_ref_pics_sps);
        for (int i = 0; i < sps->num_long_term_ref_pics_sps; i++)
        {
            sps->lt_ref_pic_poc_lsb_sps_bytes = sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
            sps->lt_ref_pic_poc_lsb_sps[i] = bs_read_u(b, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); // u(v)
            sps->used_by_curr_pic_lt_sps_flag[i] = bs_read_u1(b);
        }
    }

    sps->sps_temporal_mvp_enabled_flag = bs_read_u1(b);
    sps->strong_intra_smoothing_enabled_flag = bs_read_u1(b);
    sps->vui_parameters_present_flag = bs_read_u1(b);
    if (sps->vui_parameters_present_flag)
    {
        h265_read_vui_parameters(&(sps->vui), b, sps->sps_max_sub_layers_minus1);
        // calc fps
        if (sps->vui.vui_num_units_in_tick != 0)
            h->info->max_framerate = (float)(sps->vui.vui_time_scale) / (float)(sps->vui.vui_num_units_in_tick);
    }

    sps->sps_extension_present_flag = bs_read_u1(b);
    if (sps->sps_extension_present_flag)
    {
        sps->sps_range_extension_flag      = bs_read_u1(b);
        sps->sps_multilayer_extension_flag = bs_read_u1(b);
        sps->sps_3d_extension_flag         = bs_read_u1(b);
        sps->sps_extension_5bits           = bs_read_u(b, 5);
    }

    if (sps->sps_range_extension_flag)
    {
        sps->sps_range_extension.transform_skip_rotation_enabled_flag    = bs_read_u1(b);
        sps->sps_range_extension.transform_skip_context_enabled_flag     = bs_read_u1(b);
        sps->sps_range_extension.implicit_rdpcm_enabled_flag             = bs_read_u1(b);
        sps->sps_range_extension.explicit_rdpcm_enabled_flag             = bs_read_u1(b);
        sps->sps_range_extension.extended_precision_processing_flag      = bs_read_u1(b);
        sps->sps_range_extension.intra_smoothing_disabled_flag           = bs_read_u1(b);
        sps->sps_range_extension.high_precision_offsets_enabled_flag     = bs_read_u1(b);
        sps->sps_range_extension.persistent_rice_adaptation_enabled_flag = bs_read_u1(b);
        sps->sps_range_extension.cabac_bypass_alignment_enabled_flag     = bs_read_u1(b);
    }
    if (sps->sps_multilayer_extension_flag)
    {
        // sps_multilayer_extension()
        sps->inter_view_mv_vert_constraint_flag = bs_read_u1(b);
    }
    if (sps->sps_3d_extension_flag)
    {
        // todo sps_3d_extension( )
    }
    if (sps->sps_extension_5bits)
    {
        while (h265_more_rbsp_trailing_data(b))
        {
            int sps_extension_data_flag = bs_read_u1(b);
        }
    }
    h265_read_rbsp_trailing_bits(b);
}


void h265_sei_free(h265_sei_t* s)
{
    if (s == NULL) return;
    if ( s->payload != NULL ) free(s->payload);
    free(s);
}


/**
 Free an existing H265 stream object.  Frees all contained structures.
 @param[in,out] h   the stream object
 */
void h265_free(h265_stream_t* h)
{
    free(h->nal);
    for ( int i = 0; i < 16; i++ ) { if (h->vps_table[i]!=NULL) free( h->vps_table[i] ); }
    for ( int i = 0; i < 32; i++ ) { if (h->sps_table[i]!=NULL) free( h->sps_table[i] ); }
    for ( int i = 0; i < 256; i++ ) { if (h->pps_table[i]!=NULL) free( h->pps_table[i] ); }

    if (h->aud != NULL)
    {
        free(h->aud);
    }

    if(h->seis != NULL)
    {
        for( int i = 0; i < h->num_seis; i++ )
        {
            h265_sei_t* sei = h->seis[i];
            h265_sei_free(sei);
        }
        free(h->seis);
    }
    free(h->sh);
    free(h->info);
    free(h);
}


/**
 Create a new H265 stream object.  Allocates all structures contained within it.
 @return    the stream object
 */
h265_stream_t* h265_new()
{
    h265_stream_t* h = (h265_stream_t*)calloc(1, sizeof(h265_stream_t));

    h->nal = (h265_nal_t*)calloc(1, sizeof(h265_nal_t));

    // initialize tables
    for ( int i = 0; i < 16; i++ ) { h->vps_table[i] = (h265_vps_t*)calloc(1, sizeof(h265_vps_t)); }
    for ( int i = 0; i < 32; i++ ) { h->sps_table[i] = (h265_sps_t*)calloc(1, sizeof(h265_sps_t)); }
    for ( int i = 0; i < 256; i++ ) { h->pps_table[i] = (h265_pps_t*)calloc(1, sizeof(h265_pps_t)); }

    h->vps = h->vps_table[0];
    h->sps = h->sps_table[0];
    h->pps = h->pps_table[0];
    h->aud = (h265_aud_t*)calloc(1, sizeof(h265_aud_t));
    h->num_seis = 0;
    h->seis = NULL;
    h->sei = NULL;  //This is a TEMP pointer at whats in h->seis...
    h->sh = (h265_slice_header_t*)calloc(1, sizeof(h265_slice_header_t));

    h->info = (videoinfo_t*)calloc(1, sizeof(videoinfo_t));
    h->info->type = 1;
    return h;
}


/**
 Read a NAL unit from a byte buffer.
 The buffer must start exactly at the beginning of the nal (after the start prefix).
 The NAL is read into h->nal and into other fields within h depending on its type (check h->nal->nal_unit_type after reading).
 @param[in,out] h          the stream object
 @param[in]     buf        the buffer
 @param[in]     size       the size of the buffer
 @return                   the length of data actually read, or -1 on error
 */
//7.3.1 NAL unit syntax
int h265_read_nal_unit(h265_stream_t* h, uint8_t* buf, int size)
{
    h265_nal_t* nal = h->nal;

    bs_t* b = bs_new(buf, size);
    // nal header
    nal->forbidden_zero_bit = bs_read_f(b,1);
    nal->nal_unit_type = bs_read_u(b,6);
    nal->nuh_layer_id = bs_read_u(b,6);
    nal->nuh_temporal_id_plus1 = bs_read_u(b,3);
    nal->parsed = NULL;
    nal->sizeof_parsed = 0;
    bs_free(b);

    int nal_size = size;
    int rbsp_size = size;
    uint8_t* rbsp_buf = (uint8_t*)malloc(rbsp_size);

    int rc = nal_to_rbsp(2, buf, &nal_size, rbsp_buf, &rbsp_size);

    if (rc < 0) { free(rbsp_buf); return -1; } // handle conversion error

    b = bs_new(rbsp_buf, rbsp_size);

    // nal data
    switch ( nal->nal_unit_type )
    {
        case NAL_UNIT_VPS:
            //h265_read_vps_rbsp(h,b);
            break;
        case NAL_UNIT_SPS:
            h265_read_sps_rbsp(h, b);
            nal->parsed = h->sps;
            nal->sizeof_parsed = sizeof(h265_sps_t);
            break;
        case NAL_UNIT_PPS:
            break;
        case NAL_UNIT_PREFIX_SEI:
            break;
        case NAL_UNIT_SUFFIX_SEI: 
            break;
        case NAL_UNIT_AUD:
            break;
        case NAL_UNIT_EOS:
            break;
        case NAL_UNIT_EOB:
            break;
        case NAL_UNIT_CODED_SLICE_TRAIL_N:
        case NAL_UNIT_CODED_SLICE_TRAIL_R:
        case NAL_UNIT_CODED_SLICE_TSA_N:
        case NAL_UNIT_CODED_SLICE_TSA_R:
        case NAL_UNIT_CODED_SLICE_STSA_N:
        case NAL_UNIT_CODED_SLICE_STSA_R:
        case NAL_UNIT_CODED_SLICE_RADL_N:
        case NAL_UNIT_CODED_SLICE_RADL_R:
        case NAL_UNIT_CODED_SLICE_RASL_N:
        case NAL_UNIT_CODED_SLICE_RASL_R:
        case NAL_UNIT_CODED_SLICE_BLA_W_LP:
        case NAL_UNIT_CODED_SLICE_BLA_W_RADL:
        case NAL_UNIT_CODED_SLICE_BLA_N_LP:
        case NAL_UNIT_CODED_SLICE_IDR_W_RADL:
        case NAL_UNIT_CODED_SLICE_IDR_N_LP:
        case NAL_UNIT_CODED_SLICE_CRA:
            //h265_read_slice_layer_rbsp(h, b);
            //nal->parsed = h->sh;
            //nal->sizeof_parsed = sizeof(h265_slice_header_t);
            break;
        case NAL_UNIT_RESERVED_VCL_N10:
        case NAL_UNIT_RESERVED_VCL_R11:
        case NAL_UNIT_RESERVED_VCL_N12:
        case NAL_UNIT_RESERVED_VCL_R13:
        case NAL_UNIT_RESERVED_VCL_N14:
        case NAL_UNIT_RESERVED_VCL_R15:

        case NAL_UNIT_RESERVED_IRAP_VCL22:
        case NAL_UNIT_RESERVED_IRAP_VCL23:

        case NAL_UNIT_RESERVED_VCL24:
        case NAL_UNIT_RESERVED_VCL25:
        case NAL_UNIT_RESERVED_VCL26:
        case NAL_UNIT_RESERVED_VCL27:
        case NAL_UNIT_RESERVED_VCL28:
        case NAL_UNIT_RESERVED_VCL29:
        case NAL_UNIT_RESERVED_VCL30:
        case NAL_UNIT_RESERVED_VCL31:
            printf ("Note: found reserved VCL NAL unit.\n");
            nal->parsed = NULL;
            nal->sizeof_parsed = 0;
            break;
        case NAL_UNIT_RESERVED_NVCL41:
        case NAL_UNIT_RESERVED_NVCL42:
        case NAL_UNIT_RESERVED_NVCL43:
        case NAL_UNIT_RESERVED_NVCL44:
        case NAL_UNIT_RESERVED_NVCL45:
        case NAL_UNIT_RESERVED_NVCL46:
        case NAL_UNIT_RESERVED_NVCL47:
            printf ("Note: found reserved NAL unit.\n");
            nal->parsed = NULL;
            nal->sizeof_parsed = 0;
            break;
        case NAL_UNIT_UNSPECIFIED_48:
        case NAL_UNIT_UNSPECIFIED_49:
        case NAL_UNIT_UNSPECIFIED_50:
        case NAL_UNIT_UNSPECIFIED_51:
        case NAL_UNIT_UNSPECIFIED_52:
        case NAL_UNIT_UNSPECIFIED_53:
        case NAL_UNIT_UNSPECIFIED_54:
        case NAL_UNIT_UNSPECIFIED_55:
        case NAL_UNIT_UNSPECIFIED_56:
        case NAL_UNIT_UNSPECIFIED_57:
        case NAL_UNIT_UNSPECIFIED_58:
        case NAL_UNIT_UNSPECIFIED_59:
        case NAL_UNIT_UNSPECIFIED_60:
        case NAL_UNIT_UNSPECIFIED_61:
        case NAL_UNIT_UNSPECIFIED_62:
        case NAL_UNIT_UNSPECIFIED_63:
            printf ("Note: found unspecified NAL unit.\n");
            nal->parsed = NULL;
            nal->sizeof_parsed = 0;
            break;
        default:
            // here comes the reserved/unspecified/ignored stuff
            nal->parsed = NULL;
            nal->sizeof_parsed = 0;
            return 0;
    }

    if (bs_overrun(b)) { bs_free(b); free(rbsp_buf); return -1; }

    bs_free(b);
    free(rbsp_buf);

    return nal_size;
}



#endif